#include "Filter.h"
#include <QDebug>

Filter::Filter(int inputsCount, int outputsCount) :
		outputs(nullptr),
		inputs(nullptr),
		ready(false),
		inputsCount(inputsCount),
		outputsCount(outputsCount),
		endOfStream(false)
{
	outputs = new cv::Mat[outputsCount];
	inputs = new cv::Mat *[inputsCount];

	outputValid = new bool[outputsCount];
	inputValid = new bool *[inputsCount];

	for (int i = 0; i < outputsCount; ++i)
	{
		outputValid[i] = false;
	}

	inputFilters.resize(inputsCount);

	for (int i = 0; i < inputsCount; ++i)
	{
		inputFilters[i] = std::make_pair(nullptr, 0);
	}
}

Filter::~Filter(void)
{
	delete[] outputs;
	delete[] inputs;
	delete[] outputValid;
	delete[] inputValid;
}

void Filter::RunProcess()
{
	if (!ready)
	{
		bool allInputsValid = true;
		for (int i = 0; i < inputsCount; ++i)
		{
			if (!(*inputValid[i]))
			{
				allInputsValid = false;
				break;
			}
		}

		if (allInputsValid)
		{
			for (int j = 0; j < outputsCount; ++j)
				outputValid[j] = true;
			Process();
		}
		else
			ProcessInvalid();

		ready = true;
	}
}

void Filter::ProcessInvalid()
{
	//standard behavior, can be overwriten

	for (int i = 0; i < outputsCount; ++i)
	{
		outputValid[i] = false;
	}
}

QString Filter::GetFilterName()
{
	QString name = QString::fromStdString(typeid(*this).name());
	return name.right(name.length() - 6);
}

bool Filter::GetEndOfStream()
{
	return endOfStream;
}

bool Filter::IsReady()
{
	return ready;
}

void Filter::NextFrame()
{
	ready = false;
}

void Filter::ConnectInput(int inputIndex, Filter &filter, int outputIndex)
{
	if (inputsCount <= inputIndex)
		throw InputOutputIndexOutOfBoundsException(inputIndex, inputsCount - 1, this, &filter);
	if (filter.outputsCount <= outputIndex)
		throw InputOutputIndexOutOfBoundsException(outputIndex, outputsCount - 1, this, &filter);

	inputFilters[inputIndex] = std::make_pair(&filter, outputIndex);
	inputs[inputIndex] = &(filter.outputs[outputIndex]);
	inputValid[inputIndex] = &(filter.outputValid[outputIndex]);
}

void Filter::ConnectInput(Filter &filter)
{
	ConnectInput(0, filter, 0);
}

Filter *Filter::GetInputFilter(int inputIndex)
{
	return inputFilters[inputIndex].first;
}

QWidget *Filter::GetPropertiesWidget()
{
	return nullptr;
}

QWidget *Filter::GetOutputWidget()
{
	return nullptr;
}
